<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel="stylesheet" href="./css/Re5-2022-10-25-lidare.css">
</head>

<body>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.1/jquery.js"></script>
    <script>
        jQuery(function () {
            var img = "url(./images/game.png)";
            function Game(parent, cat, img) {
                this.parent = parent;
                cat ? this.cat = cat : this.cat = 3;
                this.backgroundImage = img;
                this.width = Math.floor(jQuery(this.parent).width() / cat);
                this.height = Math.floor(jQuery(this.parent).height() / cat);
                this.where = Math.floor(Math.random() * (cat * cat - 1));
                this.left = 0;
                this.top = 0;
                this.blank = null;
                this.mask = [];
                this.intercept = false;
                this.allItem = [];
                this.box = null;
                this.game = null;
                this.how = false;
                this.createGame();
                this.init();
                this.bindEvent();
            }
            Game.prototype.createGame = function () {
                var gamebox = jQuery(`<div class="gameBox"></div>`);
                this.game = jQuery(`
                <div class="game">
                    <div class="all">
                        <div class="box"></div>
                        <div class="map"></div>
                        <select class="select">
                            <option value="2">2 X 2</option>
                            <option value="3" selected>3 X 3</option>
                            <option value="6">6 X 6</option>
                            <option value="9">9 X 9</option>
                        </select>
                    </div>
                    <div class="reset">重置</div>
                </div>`);
                this.game.appendTo(gamebox);
                gamebox.appendTo(this.parent);
            }
            Game.prototype.init = function () {
                jQuery(this.game).find(".select")[0].value = this.cat;
                var self = this;
                this.box = this.game.find(".box");
                jQuery(this.box).html("");
                this.width = Math.floor(jQuery(this.box).width() / this.cat);
                this.height = Math.floor(jQuery(this.box).height() / this.cat);
                this.where = Math.floor(Math.random() * (this.cat * this.cat - 1));
                this.left = 0;
                this.top = 0;
                this.blank = null;
                this.mask = [];
                this.intercept = false;
                this.allItem = [];
                jQuery(this.game).find(".map").css({
                    backgroundImage: this.backgroundImage
                });
                for (var i = 0; i < this.cat; i++) {
                    var mas = [];
                    for (var j = 0; j < this.cat; j++) {
                        var item = jQuery(`<div class="item"></div>`).appendTo(this.box).css({
                            width: this.width,
                            height: this.height
                        });
                        item.css({
                            left: this.width * j,
                            top: this.height * i,
                            backgroundImage: this.where == item.index() ? "" : this.backgroundImage,
                            backgroundPosition: `-${this.width * j}px -${this.height * i}px`
                        });
                        if (this.where == item.index()) {
                            self.left = item.position().left;
                            self.top = item.position().top;
                            this.blank = item;
                            this.blank.data({
                                coordinates: [i, j]
                            }).css({
                                zIndex: 10
                            });
                        }
                        this.mask.push(`${item.position().left},${item.position().top}`);
                        mas.push(item);
                    }
                    this.allItem.push(mas);

                }

                var num = 0;
                while (++num <= 2000) {
                    this.Roadrunner();
                }
                num = 0;
                var toArr = [];
                while (num++ < this.cat) {
                    toArr = toArr.concat([...this.allItem[num - 1]]);
                }
                var items = jQuery(this.box).find(".item");
                for (var dot = 0; dot < toArr.length; dot++) {
                    var position = jQuery(items[toArr[dot].index()]).position();
                    jQuery(items[toArr[dot].index()]).css({
                        left: jQuery(items[dot]).position().left,
                        top: jQuery(items[dot]).position().top
                    });
                }
                // function Roadrunner() {
                //     var arr = copyArr(self.allItem, self.cat),
                //         coordinates = self.blank.data("coordinates"),
                //         num = Math.floor(Math.random() * 4);
                //     switch (num) {
                //         case 0:
                //             var ma = coordinates[0] - 1;
                //             if (ma < 0) break;
                //             arr[coordinates[0]][coordinates[1]] = arr[ma][coordinates[1]];
                //             arr[ma][coordinates[1]] = self.blank;
                //             coordinates[0]--;
                //             break;
                //         case 3:
                //             var ma = coordinates[0] + 1;
                //             if (ma >= self.cat) break;
                //             arr[coordinates[0]][coordinates[1]] = arr[ma][coordinates[1]];
                //             arr[ma][coordinates[1]] = self.blank;
                //             coordinates[0]++;
                //             break;
                //         case 1:
                //             var ma = coordinates[1] - 1;
                //             if (ma < 0) break;
                //             arr[coordinates[0]][coordinates[1]] = arr[coordinates[0]][ma];
                //             arr[coordinates[0]][ma] = self.blank;
                //             coordinates[1]--;
                //             break;
                //         case 2:
                //             var ma = coordinates[1] + 1;
                //             if (ma >= self.cat) break;
                //             arr[coordinates[0]][coordinates[1]] = arr[coordinates[0]][ma];
                //             arr[coordinates[0]][ma] = self.blank;
                //             coordinates[1]++;
                //             break;
                //     }
                //     self.allItem = arr;
                //     function copyArr(allItem, cat) {
                //         var arr = [];
                //         for (var i = 0; i < cat; i++) {
                //             arr[i] = [];
                //             for (var j = 0; j < cat; j++) {
                //                 arr[i][j] = allItem[i][j];
                //             }
                //         }
                //         return arr;
                //     }
                // }
            }
            Game.prototype.Roadrunner = function () {
                var arr = copyArr(this.allItem, this.cat),
                    coordinates = this.blank.data("coordinates"),
                    num = Math.floor(Math.random() * 4);
                switch (num) {
                    case 0:
                        var ma = coordinates[0] - 1;
                        if (ma < 0) break;
                        arr[coordinates[0]][coordinates[1]] = arr[ma][coordinates[1]];
                        arr[ma][coordinates[1]] = this.blank;
                        coordinates[0]--;
                        break;
                    case 3:
                        var ma = coordinates[0] + 1;
                        if (ma >= this.cat) break;
                        arr[coordinates[0]][coordinates[1]] = arr[ma][coordinates[1]];
                        arr[ma][coordinates[1]] = this.blank;
                        coordinates[0]++;
                        break;
                    case 1:
                        var ma = coordinates[1] - 1;
                        if (ma < 0) break;
                        arr[coordinates[0]][coordinates[1]] = arr[coordinates[0]][ma];
                        arr[coordinates[0]][ma] = this.blank;
                        coordinates[1]--;
                        break;
                    case 2:
                        var ma = coordinates[1] + 1;
                        if (ma >= this.cat) break;
                        arr[coordinates[0]][coordinates[1]] = arr[coordinates[0]][ma];
                        arr[coordinates[0]][ma] = this.blank;
                        coordinates[1]++;
                        break;
                }
                this.allItem = arr;
                function copyArr(allItem, cat) {
                    var arr = [];
                    for (var i = 0; i < cat; i++) {
                        arr[i] = [];
                        for (var j = 0; j < cat; j++) {
                            arr[i][j] = allItem[i][j];
                        }
                    }
                    return arr;
                }
            }
            Game.prototype.bindEvent = function () {
                var self = this;
                jQuery(this.box).on({
                    click: function (e) {
                        if (self.intercept || e.target == self.blank[0]) return;
                        self.intercept = true;
                        var position = jQuery(this).position(),
                            offset = 10,
                            check1 = (position.left <= self.left + offset && position.left >= self.left - offset) && (position.top + self.height <= self.top + offset && position.top + self.height >= self.top - offset),
                            check2 = (position.left + self.width <= self.left + offset && position.left + self.width >= self.left - offset) && (position.top <= self.top + offset && position.top >= self.top - offset),
                            check3 = (position.left - self.width <= self.left + offset && position.left - self.width >= self.left - offset) && (position.top <= self.top + offset && position.top >= self.top - offset),
                            check4 = (position.left <= self.left + offset && position.left >= self.left - offset) && (position.top - self.height <= self.top + offset && position.top - self.height >= self.top - offset);
                        if (check1) {
                            jQuery(this).css({
                                top: position.top + self.height
                            });
                            self.blank.css({
                                top: self.blank.position().top - self.height
                            })
                        } else if (check2) {
                            jQuery(this).css({
                                left: position.left + self.width
                            });
                            self.blank.css({
                                left: self.blank.position().left - self.width
                            });
                        } else if (check3) {
                            jQuery(this).css({
                                left: position.left - self.width
                            });
                            self.blank.css({
                                left: self.blank.position().left + self.width
                            });
                        } else if (check4) {
                            jQuery(this).css({
                                top: position.top - self.height
                            });
                            self.blank.css({
                                top: self.blank.position().top + self.height
                            });
                        } else {
                            self.intercept = false;
                            return;
                        }
                    },
                    transitionend: function (e) {
                        self.left = self.blank.position().left;
                        self.top = self.blank.position().top;
                        self.intercept = false;
                        var items = jQuery(self.box).find(".item"),
                            check = true;
                            offset = 0;
                        for (var i = 0; i < items.length; i++) {
                            var arr = self.mask[i].split(",");
                            var check1 = parseInt(arr[0]) <= jQuery(items[i]).position().left + offset && parseInt(arr[0]) >= jQuery(items[i]).position().left - offset;
                            var check2 = parseInt(arr[1]) <= jQuery(items[i]).position().top + offset && parseInt(arr[1]) >= jQuery(items[i]).position().top - offset;
                            if (!check1 || !check2) {
                                check = false;
                                break;
                            }
                        }
                        if (check) {
                            self.blank.css({
                                backgroundImage: self.backgroundImage,
                                backgroundPosition: `-${self.blank.position().left}px -${self.blank.position().top}px`
                            });
                            jQuery(`<div class="mask"></div>`).css({
                                backgroundImage: self.backgroundImage
                            }).appendTo(self.box);
                        }
                    }
                }, ".item");
                jQuery(this.game).find(".reset").on({
                    click: function () {
                        self.init();
                    }
                });
                jQuery(this.game).find(".select").on({
                    change: function () {
                        self.cat = parseInt(this.value);
                        self.init();
                    }
                });
            }
            new Game(document.body, 3, img);
            new Game(document.body, 6, img);
        });
    </script>
</body>

</html>